Package com.golden.gamedev.engine.network

Source Code of com.golden.gamedev.engine.network.PacketManager

/*
* PacketManager.java
*
* Created on May 10, 2007, 1:04 PM
*
*
* Copyright (c) 2008 Golden T Studios.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.golden.gamedev.engine.network;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import com.golden.gamedev.engine.network.manipulator.DataEncryption;
import com.golden.gamedev.engine.network.manipulator.DataObfuscation;
import com.golden.gamedev.engine.network.packet.NetworkMessage;
import com.golden.gamedev.engine.network.packet.NetworkPing;

/**
*
* @author Paulus Tuerah
*/
public class PacketManager {
 
  public int BUFFER_SIZE = 2048; // bigger than any packable
 
  private short[] registeredID = new short[0]; // registered packet id
  private Object[] registeredObject = new Object[0]; // registered packet
                            // object (NetworkPacket
                            // class or object)
 
  // for security, we encrypt and obfuscate the packet
  private DataManipulator[] manipulator = new DataManipulator[] {
          new DataEncryption(), new DataObfuscation()
  };
 
  /** ************************************************************************* */
  /** ***************************** CONSTRUCTOR ******************************* */
  /** ************************************************************************* */
 
  /**
   * Creates a new instance of PacketManager
   */
  public PacketManager() {
  }
 
  public void registerPacket(short id, NetworkPacket packet) {
    // if (NetworkConfig.DEBUG) {
    // System.out.println("Register ID " + id + " for packet " + packet);
    // }
   
    if (packet.getID() == NetworkPacket.NULL_ID) {
      throw new RuntimeException("Packet ID " + packet + " must be set "
              + "either by passing NetworkPacket.setID(short) or "
              + "by overriding NetworkPacket.getID() method");
    }
   
    for (int i = 0; i < this.registeredID.length; i++) {
      if (this.registeredID[i] == id) {
        throw new RuntimeException("ID " + id
                + " is already registered with "
                + this.registeredObject[i]);
      }
    }
   
    this.registeredID = (short[]) NetworkUtil.expand(this.registeredID, 1);
    this.registeredObject = (Object[]) NetworkUtil.expand(
            this.registeredObject, 1);
   
    int len = this.registeredID.length - 1;
    this.registeredID[len] = id;
    this.registeredObject[len] = packet;
  }
 
  public void registerPacket(short id, Class packetClass) {
    // if (NetworkConfig.DEBUG) {
    // String className = packetClass.getName();
    // int index = className.lastIndexOf(".");
    // if (index != -1) {
    // className = className.substring(index + 1);
    // }
    //
    // System.out.println("Register ID " + id + " for packet class " +
    // className);
    // }
   
    if (!NetworkPacket.class.isAssignableFrom(packetClass)) {
      throw new RuntimeException("Unable to register packet class "
              + packetClass + ", not subclass of NetworkPacket class.");
    }
   
    for (int i = 0; i < this.registeredID.length; i++) {
      if (this.registeredID[i] == id) {
        throw new RuntimeException("ID " + id
                + " is already registered with "
                + this.registeredObject[i]);
      }
    }
   
    this.registeredID = (short[]) NetworkUtil.expand(this.registeredID, 1);
    this.registeredObject = (Object[]) NetworkUtil.expand(
            this.registeredObject, 1);
   
    int len = this.registeredID.length - 1;
    this.registeredID[len] = id;
    this.registeredObject[len] = packetClass;
  }
 
  public synchronized byte[] pack(NetworkPacket packet) throws IOException {
    ByteArrayOutputStream baout = new ByteArrayOutputStream(); // the byte
                                  // array
                                  // stream
    DataOutputStream output = new DataOutputStream(baout);
   
    // write the packet id
    output.writeShort(this.getPacketID(packet));
   
    // compress the packet
    if (packet.isCompressed()) {
      output = this.compress(output);
    }
   
    // write the packet data
    packet.writePacket(output);
   
    output.close();
   
    byte[] data = baout.toByteArray();
   
    // manipulate packet for security
    if (this.manipulator != null) {
      try {
        for (int i = 0; i < this.manipulator.length; i++) {
          data = this.manipulator[i].manipulate(data);
        }
       
      }
      catch (Exception ex) {
        ex.printStackTrace();
        throw new IOException(ex.getMessage());
      }
    }
   
    return data;
  }
 
  public synchronized NetworkPacket unpack(byte[] data) throws IOException {
    // demanipulate packet data first
    if (this.manipulator != null) {
      try {
        for (int i = this.manipulator.length - 1; i >= 0; i--) {
          data = this.manipulator[i].demanipulate(data);
        }
       
      }
      catch (Exception ex) {
        ex.printStackTrace();
        throw new IOException(ex.getMessage());
      }
    }
   
    ByteArrayInputStream bain = new ByteArrayInputStream(data);
    DataInputStream input = new DataInputStream(bain);
   
    // read the packet id
    short packetID = input.readShort();
   
    // create the packet
    NetworkPacket packet = null;
   
    // read the packet data
    if (packetID == NetworkPing.ID) {
      // ping packet
      packet = NetworkPing.getInstance();
     
    }
    else {
      // network packet
      packet = (packetID == NetworkMessage.ID) ? new NetworkMessage()
              : this.createPacket(packetID);
     
      // decompress
      if (packet.isCompressed()) {
        input = this.decompress(input);
      }
     
      // construct the packet
      packet.readPacket(input);
    }
   
    input.close();
   
    return packet;
  }
 
  protected short getPacketID(NetworkPacket packet) {
    if (packet.getID() != NetworkPacket.NULL_ID) {
      // packet id is already set
      // for example on new NetworkObject(UNIQUE_ID);
      return packet.getID();
    }
   
    // packet id is not set (null id)
    // we need to get the real packet id
    // from the type of the packet class
   
    Class packetClass = packet.getClass();
   
    for (int i = 0; i < this.registeredID.length; i++) {
      if (packetClass.equals(this.registeredObject[i])) {
        return this.registeredID[i];
      }
    }
   
    throw new RuntimeException(
            packetClass
                    + " class has not been registered.\n"
                    + "Use NetworkConfig.registerPacket(short id, Class packetClass) to register the packet id.");
  }
 
  protected NetworkPacket createPacket(short id) {
    NetworkPacket packet = null;
   
    // construct the packet based on its id
    // if it's a class, create new instance
    // if it's an object, we clone it
    for (int i = 0; i < this.registeredID.length; i++) {
      if (this.registeredID[i] == id) {
        Object type = this.registeredObject[i];
       
        if (type instanceof Class) {
          // class type
          // create new instance
          try {
            packet = (NetworkPacket) ((Class) type).newInstance();
           
          }
          catch (Exception ex) {
            throw new RuntimeException(ex);
          }
         
        }
        else {
          // NetworkPacket object, clone from the object
          try {
            packet = (NetworkPacket) ((NetworkPacket) type).clone();
           
          }
          catch (Exception ex) {
            throw new RuntimeException(ex);
          }
        }
       
        break;
      }
    }
   
    if (packet == null) {
      throw new RuntimeException(
              "ID "
                      + id
                      + " has not been registered.\n"
                      + "Use NetworkConfig.registerPacket(short id, Class packetClass) to register the packet id.");
    }
   
    packet.setID(id);
   
    return packet;
  }
 
  protected DataOutputStream compress(DataOutputStream output)
          throws IOException {
    return new DataOutputStream(new GZIPOutputStream(output,
            this.BUFFER_SIZE));
  }
 
  protected DataInputStream decompress(DataInputStream input)
          throws IOException {
    return new DataInputStream(new GZIPInputStream(input, this.BUFFER_SIZE));
  }
 
  public short[] getRegisteredID() {
    return this.registeredID;
  }
 
  public Object[] getRegisteredObject() {
    return this.registeredObject;
  }
 
  public DataManipulator[] getDataManipulator() {
    return this.manipulator;
  }
 
  public void setDataManipulator(DataManipulator[] dataManipulator) {
    this.manipulator = dataManipulator;
  }
 
}
TOP

Related Classes of com.golden.gamedev.engine.network.PacketManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.